﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Windows.Forms;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.AccessControl;
using Google.Documents;
using Google.GData.Documents;
using Google.Contacts;
using DataType;
using LocalView;
using System.IO;
using System.Diagnostics;
using System.Web.Mail;
using LicenseManager;
using Utilities;
using ContentProcessor;
using System.Net;
using System.Threading;
using Microsoft.Win32; 

namespace UILibrary
{
    public partial class MyGDocsForm : UserControl
    {
        internal delegate void BuildStructureDelegate();
        internal delegate void VoidDelegate();
        
        public ILocalView m_LocalView;
        public ThreadSafeUIOperations m_TS_UI;
        public TreeViewDocuments m_Tree;
        private DbOperations m_dbOperations;
        TraceWrapper m_traceWrapper;
        SnapshotManager m_snapshot;
        public bool m_multithreadSupported = true;
        System.Windows.Forms.Button m_copyBtn;

        Progress m_progressDlg;
        WebContent m_webContent;
        ImageList m_ImageList;

        public MyGDocsForm(ILocalView LocalView, 
                            bool disabled, 
                            DbOperations dbOperations, 
                            TraceWrapper traceWrapper, 
                            SnapshotManager _snapshot,
                            Document.DocumentType type)
        {
            InitializeComponent();

            m_progressDlg = new Progress();
            m_webContent = new LinkedInContent();

            ActionPaneBuilder.layoutControls(this);
        
            m_LocalView = LocalView;
            m_dbOperations = dbOperations;
            m_traceWrapper = traceWrapper;
            m_snapshot = _snapshot;

            m_Tree = new TreeViewDocuments(this.documentsView, type);
            m_TS_UI = new ThreadSafeUIOperations();
            readerRadioButton.Checked = true;
            //LoginProgress.Visible = true;
            UpdateBtn.Enabled = false;
            RefreshButton.Enabled = false;
            RegistrationLink.Visible = false;
            ShareButton.Enabled = false;
            FeedbackBtn.Enabled = false;
            SupportMsg.Text = Properties.Resources.SupportTemplate;
            btnSearch.Enabled = false;
            btnAddMail.Enabled = false; 

            RegistryKey kHKCU = Registry.CurrentUser;
            RegistryKey kFirstRun;

            kFirstRun = kHKCU.OpenSubKey("Software\\UpriseApps\\OfficeInCloud", true);
            if (kFirstRun == null)
            {
                kFirstRun = kHKCU.CreateSubKey("Software\\UpriseApps\\OfficeInCloud", RegistryKeyPermissionCheck.ReadWriteSubTree);
                kFirstRun.SetValue("ProxyType", 0);
                // 0 - No Proxy
                // 1 - IE Proxy
                // 2 - Manual Proxy
            }
            if ((int)kFirstRun.GetValue("ProxyType") == 0) radioNoProxy.Checked = true;
            if ((int)kFirstRun.GetValue("ProxyType") == 1) radioIEProxy.Checked = true;
            if ((int)kFirstRun.GetValue("ProxyType") == 2)
            {
                radioManualProxy.Checked = true;
                maskedTextBox1.Text = (string)kFirstRun.GetValue("ProxyAddress");
                maskedTextBox2.Text = (string)kFirstRun.GetValue("ProxyPort");
                //string[] arr = ((string)kFirstRun.GetValue("ProxyAddress")).Split(new char[':']);
                //if (arr.Length > 1)
                //    maskedTextBox2.Text = arr[1];
                textBox3.Text = (string)kFirstRun.GetValue("UserName");
                textBox4.Text = (string)kFirstRun.GetValue("Password"); 
            }

            Credentials cred = new Credentials(null, null);
            m_dbOperations.DoLoadCredentials(cred);

            if (cred.m_remember == true) {
                UserName.Text = cred.m_Cred.Username;
                Password.Text = cred.m_password;
                checkRemember.Checked = cred.m_remember; 
            }

            if (disabled)
            {
                UserName.Enabled = false;
                Password.Enabled = false;
                checkRemember.Enabled = false;
                LoginButton.Enabled = false;
                RegistrationLink.Visible = true;
            }
        }

        private void MyGDocsForm_Resize(object sender, EventArgs e)
        {
            this.MyGDocsTabControl.Size = this.Size;
        }

        private void AddListBoxItem(string Msg, bool CheckState)
        {
            this.ContactListBox.Items.Add(Msg, false);
        }

        //private void SwitchOnProgress(PictureBox pb) {
        //    pb.Visible = true; 
        //} 

        private void AddContact2UI(Contact contact)
        {
            if ((contact.ContactEntry.Emails.Count == 0) || (contact.ContactEntry.Emails[0].Address.Length == 0))
                return;
            if (contact.Title != "") 
                m_TS_UI.AddListBoxItem(this.ContactListBox, contact.Title + " (" + contact.ContactEntry.Emails[0].Address + ")", false);
            else
                m_TS_UI.AddListBoxItem(this.ContactListBox, contact.ContactEntry.Emails[0].Address, false);
            
        }   

        private void BuildContacts()
        {
            FeedWrapper<Contact> feed = new FeedWrapper<Contact>();
            m_LocalView.DoGetContacts(feed);
            foreach (Contact cnt in feed.m_Feed.Entries)
                AddContact2UI(cnt);
            //m_LocalView.DoGetContactsAsync(this.AddContact2UI);
        }

        private void BuildDocuments()
        {
            m_Tree.InitTree();
            FeedWrapper<Document> feed = new FeedWrapper<Document>();
            m_LocalView.DoGetDocuments(feed);

            foreach (Document entry in feed.m_Feed.Entries) m_Tree.AddDocumentToCollection(entry);

            m_Tree.ShowTree();
        }

        private void BuildDataStructure()
        {
            try
            {
                BuildContacts();
                BuildDocuments();
            }
            catch (Exception ex)
            {
                Utilities.TraceWrapper.LogException("BuildDataStructure error: " + ex.Message, ex);
                
                m_TS_UI.SetText(StatusMessage, Properties.Resources.ErrorPrefix + ex.Message);
            }
        }

        private void BuildDataStructureCallbackMethod(IAsyncResult ar)
        {
            // Retrieve the delegate.
            BuildStructureDelegate dlgt = (BuildStructureDelegate)ar.AsyncState;

            // Call EndInvoke to retrieve the results.
            dlgt.EndInvoke(ar);

            if (MyGDocsTabControl.InvokeRequired)
            {
                VoidDelegate dlgt1 = new VoidDelegate(this.SelectExplorerTab);
                MyGDocsTabControl.Invoke(dlgt1);

                //save clean state after login
                VoidDelegate dlg1 = new VoidDelegate(storeState);
                this.Invoke(dlg1);
            }
            else
            {
                MyGDocsTabControl.SelectTab("Explorer");
                storeState();
            }
        }

        private void SelectExplorerTab()
        {
            if (MyGDocsTabControl.TabPages["SignIn"].Visible)
                MyGDocsTabControl.SelectTab("Explorer");
        }


        //progress window code
        private void DoAllLogins() 
        {
            try
            {
                //LicenseManager.ZohoLicenseManager lm = new ZohoLicenseManager("info@upriseapps.com", "mamamilaramu", m_dbOperations);
                //lm.Login();
                //lm.LoadRegisteredUser();
                //lm.RegisteredContactUpdate();
                //if (lm.RegisteredContactBlocked())
                //    throw new ZohoLicenseBlocked();
                //if (lm.RegisteredLicenseExpired())
                //    throw new ZohoLicenseExpired();

                m_LocalView.DoLogin(m_LocalView.m_Cred);

                m_dbOperations.DoSaveCredentials(m_LocalView.m_Cred);

                m_TS_UI.SetEnabled(ShareButton, true);
                m_TS_UI.SetForeColor(StatusMessage, Color.Black);
                m_TS_UI.SetText(StatusMessage, Properties.Resources.LoginSucceeded);

                m_TS_UI.SetEnabled(RefreshButton, true);
                m_TS_UI.SetEnabled(FeedbackBtn, true);
                m_TS_UI.SetEnabled(UpdateBtn, true);
                m_TS_UI.SetEnabled(SignIn, false);
                m_TS_UI.SetEnabled(btnSearch, true);
                m_TS_UI.SetEnabled(btnAddMail, true);

                BuildStructureDelegate dlgt1 = new BuildStructureDelegate(this.BuildDataStructure);
                IAsyncResult ar = dlgt1.BeginInvoke(new AsyncCallback(BuildDataStructureCallbackMethod), dlgt1);
            }
            catch (AuthenticationException ex)
            {
                Utilities.TraceWrapper.LogException("Login_Click error: " + ex.Message, ex);

                m_TS_UI.SetEnabled(FeedbackBtn, false);
                m_TS_UI.SetEnabled(ShareButton, false);
                m_TS_UI.SetForeColor(StatusMessage, Color.Red);
                m_TS_UI.SetText(StatusMessage, Properties.Resources.ErrorPrefix + ex.Message);
                m_TS_UI.SetEnabled(RefreshButton, false);
            }
            catch (ZohoLicenseBlocked ex)
            {
                Utilities.TraceWrapper.LogException("Login_Click error: " + ex.Message, ex);

                MessageBox.Show("We'd like to inform you that your Office In Cloud license is blocked. \n" +
                                 "Please contact Uprise Apps support: info@upriseapps.com for details.");
            }
            catch (ZohoLicenseExpired ex)
            {
                Utilities.TraceWrapper.LogException("Login_Click error: " + ex.Message, ex);

                LicenseExpired dialog = new LicenseExpired();
                dialog.ShowDialog();
            }
            catch (ZohoUserDataException ex)
            {
                //First Run
                RegistryKey kHKCU = Registry.CurrentUser;
                RegistryKey kFirstRun;

                kFirstRun = kHKCU.OpenSubKey("Software\\UpriseApps\\OfficeInCloudExcel2007", true);
                kFirstRun = kHKCU.CreateSubKey("Software\\UpriseApps\\OfficeInCloudExcel2007", RegistryKeyPermissionCheck.ReadWriteSubTree);
                kFirstRun.SetValue("FirstRun", 1);
                MessageBox.Show("Your user data was not registered. \n Please restart the application in order to pass registration.", "Office In Cloud Error Message");
            }
            catch (Exception ex)
            {
                Utilities.TraceWrapper.LogException("Login_Click error: " + ex.Message, ex);

                m_TS_UI.SetEnabled(FeedbackBtn, false);
                m_TS_UI.SetEnabled(ShareButton, false);
                m_TS_UI.SetForeColor(StatusMessage, Color.Red);
                m_TS_UI.SetText(StatusMessage, Properties.Resources.ErrorPrefix + ex.Message);
                m_TS_UI.SetEnabled(RefreshButton, false);
            }
            finally
            {
                if (m_progressDlg.InvokeRequired)
                {
                    VoidDelegate dlg = new VoidDelegate(CloseProgreeDlg);
                    m_progressDlg.Invoke(dlg);
                }
                else m_progressDlg.Close();
            }
        }

        private void storeState()
        {
            m_snapshot.takeSnapshot("clearLogin", this);
        }

        private void CloseProgreeDlg()
        {
            m_progressDlg.Close(); 
        }


        private void VoidDelegateFormCallbackMethod(IAsyncResult ar)
        {
            VoidDelegate dlgt = (VoidDelegate)ar.AsyncState;
            dlgt.EndInvoke(ar);
            
        }
        //end

        public void DoSilentLogin()
        {
            if (m_LocalView.IsLoggedIn())
            {
                m_TS_UI.SetEnabled(ShareButton, true);
                m_TS_UI.SetForeColor(StatusMessage, Color.Black);
                m_TS_UI.SetText(StatusMessage, Properties.Resources.LoginSucceeded);

                m_TS_UI.SetEnabled(RefreshButton, true);
                m_TS_UI.SetEnabled(FeedbackBtn, true);
                m_TS_UI.SetEnabled(UpdateBtn, true);
                m_TS_UI.SetEnabled(SignIn, false);
                m_TS_UI.SetEnabled(btnSearch, true); 

                BuildStructureDelegate dlgt1 = new BuildStructureDelegate(this.BuildDataStructure);
                IAsyncResult ar = dlgt1.BeginInvoke(new AsyncCallback(BuildDataStructureCallbackMethod), dlgt1);
            }
        }

        public void Login_Click(object sender, EventArgs e)
        {
            m_TS_UI.SetVisible(StatusMessage, false);
            m_TS_UI.SetEnabled(LoginButton, false);
            //LoginProgress.Visible = true;
            m_TS_UI.SetEnabled(UserName, false);
            m_TS_UI.SetEnabled(Password, false);
            m_TS_UI.SetEnabled(checkRemember, false);
            m_TS_UI.SetEnabled(RefreshButton, false);

            m_LocalView.m_Cred = new Credentials(UserName.Text, Password.Text);
            if (checkRemember.Checked) m_LocalView.m_Cred.m_remember = true;
            else m_LocalView.m_Cred.m_remember = false;
            ContactListBox.Items.Clear();
            m_Tree.CleanUp();
            m_TS_UI.SetEnabled(ShareButton, false);

            ThreadStart newThreadStart = new ThreadStart(DoAllLogins);
            Thread newThread = new Thread(newThreadStart);

            try
            {
                //DoAllLogins(); 
                newThread.Start();
                m_progressDlg.ShowDialog(this);
            }
            finally
            {
                m_TS_UI.SetVisible(StatusMessage, true);
                m_TS_UI.SetEnabled(LoginButton, true);
                m_TS_UI.SetEnabled(UserName, true);
                m_TS_UI.SetEnabled(Password, true);
                m_TS_UI.SetEnabled(checkRemember, true);
            }
        }

        private void ShareDocument()
        {
            ILocalView.Permission perm = ILocalView.Permission.writer;
            if (readerRadioButton.Checked)
                perm = ILocalView.Permission.reader;

            string[] users = new string[ContactListBox.CheckedItems.Count];
            for (int i = 0; i < ContactListBox.CheckedItems.Count; ++i)
            {
                users[i] = ContactListBox.CheckedItems[i].ToString();
            }

            m_LocalView.DoShareDocumentsAsync(ContactListBox.CheckedItems, perm);
        }

        private enum MailNotificationTypes { Share, Update }

        private void PrepareSendMessage(MailMessage mail)
        {
            //Ensure priority is set to "NORMAL
            mail.Priority = MailPriority.Normal;
            //  Use Authentication
            mail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");
            //Use this Username to Authenticate
            mail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", this.m_LocalView.m_Cred.m_Cred.Username);
            //Use this Password to Authenticate
            mail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", this.m_LocalView.m_Cred.m_password);
            //Use STARTTLS (some clients call this SSL) - Gmail help page indicated it used this
            mail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", "true");
            // assign outgoing gmail server
            SmtpMail.SmtpServer = "smtp.gmail.com";
            SmtpMail.Send(mail);  
        }

        private void SendNotification(AclFeed feed, 
                                      string CustomSubject, 
                                      string CustomBody, 
                                      string docURL, 
                                      string docName, 
                                      MailNotificationTypes mailType)
        {
            try
            {
                MailMessage mail = new MailMessage();

                foreach (AclEntry entry in feed.Entries)
                    mail.To += (entry.Scope.Value + ";");

                if (!this.m_LocalView.m_Cred.m_Cred.Username.Contains("@"))
                    mail.From = this.m_LocalView.m_Cred.m_Cred.Username + "@gmail.com";
                else
                    mail.From = this.m_LocalView.m_Cred.m_Cred.Username;
                //System.Windows.Forms.MessageBox.Show("From = " + mail.From);


                if (CustomSubject.Trim().Length == 0)
                    mail.Subject = docName;
                else
                    mail.Subject = CustomSubject;

                switch (mailType)
                {
                    case MailNotificationTypes.Share:
                        mail.Body = Properties.Resources.MsgSharePrefix;
                        break;
                    case MailNotificationTypes.Update:
                        mail.Body = Properties.Resources.MsgUpdatePrefix;
                        break;
                }

                if (CustomBody.Trim().Length != 0)
                {
                    mail.Body += "\n";
                    mail.Body += CustomBody;
                }

                mail.Body += "\n";
                mail.Body += "\n";
                mail.Body += docName;
                mail.Body += "\n";
                mail.Body += docURL;
                mail.Body += "\n";
                mail.Body += "\n";
                mail.Body += "From Uprise Apps Office In Cloud";

                PrepareSendMessage(mail);
            }
            catch (System.Exception ex)
            {
                Utilities.TraceWrapper.LogException("SendNotification error: " + ex.Message, ex);
            }
        }

        void DoAllShareOpsThread()
        {
            m_TS_UI.SetEnabled(ShareButton, false);
            m_TS_UI.SetVisible(StatusMsgShare, false);

            try
            {
                DocumentInfo info = new DocumentInfo(m_LocalView.GetDocumentPath(), m_LocalView.GetDocumentName());

                m_LocalView.DoLookupRemoteCopy(info);
                if (info.m_DocEntry == null)
                    m_LocalView.DoSaveDocumentInCloud();
                else
                    m_LocalView.m_DocInfo = info;

                this.ShareDocument();

                //in other case the getAclList returns wrong values instead of list shared users
                System.Threading.Thread.Sleep(2000);
                ShareInfoCollection infoShare = new ShareInfoCollection(m_LocalView.m_DocInfo.m_DocEntry);
                m_LocalView.DoGetDocumentAcl(infoShare);

                if (infoShare.m_Feed.Entries.Count() != 0 && checkBoxSharedNotification.Checked)
                    this.SendNotification(infoShare.m_Feed,
                                          this.ShareSubject.Text,
                                          this.ShareMsg.Text,
                                          this.m_LocalView.GetInviteUri(),
                                          m_LocalView.m_DocInfo.m_Name,
                                          MailNotificationTypes.Share);

                m_Tree.InitTree();
                FeedWrapper<Document> feed = new FeedWrapper<Document>();
                m_LocalView.DoGetDocuments(feed);

                foreach (Document entry in feed.m_Feed.Entries) m_Tree.AddDocumentToCollection(entry);

                m_Tree.ShowTree();
            }
            catch (GDataRequestException ex)
            {
                Utilities.TraceWrapper.LogException("ShareButton_Click error: " + ex.Message, ex);

                m_TS_UI.SetForeColor(StatusMsgShare, Color.Red);
                m_TS_UI.SetText(StatusMsgShare, Properties.Resources.ErrorPrefix + ex.Message);
                m_TS_UI.SetVisible(StatusMsgShare, true);
                MessageBox.Show("Google Docs has encountered an API issue \n. In order to continue sharing operation \n please reopen the new uploaded document from Cloud.", "API Error");
            }
            catch (Exception ex)
            {
                Utilities.TraceWrapper.LogException("ShareButton_Click error: " + ex.Message, ex);

                m_TS_UI.SetForeColor(StatusMsgShare, Color.Red);
                m_TS_UI.SetText(StatusMsgShare, Properties.Resources.ErrorPrefix + ex.Message);
                m_TS_UI.SetVisible(StatusMsgShare, true);
                //Console.WriteLine(ex.Message);
            }
            finally
            {
                if (m_progressDlg.InvokeRequired)
                {
                    VoidDelegate dlg = new VoidDelegate(CloseProgreeDlg);
                    m_progressDlg.Invoke(dlg);
                }
                else m_progressDlg.Close();

                m_TS_UI.SetEnabled(ShareButton, true);
                m_TS_UI.SetEnabled(UpdateBtn, true);
            }
        }


        public void ShareButton_Click(object sender, EventArgs e)
        {
            if (m_multithreadSupported)
            {
                ThreadStart newThreadStart = new ThreadStart(DoAllShareOpsThread);
                Thread newThread = new Thread(newThreadStart);

                newThread.Start();
                m_progressDlg.ShowDialog(this);
            }
            else
                DoAllShareOpsThread();
        }

        private void tabPage1_Enter(object sender, EventArgs e)
        {
            this.documentsView.Height = this.MyGDocsTabControl.Height - 60;
            this.documentsView.Width = this.MyGDocsTabControl.Width - 30;
        }

        private void processNewDocument(Document d, Document.DownloadType type, string fileName)
        {
            //bug in SaveFileDialog if you put the filename with extension 
            //it doesn't change extension to selected in the dialog
            SaveFileDialog expDialog = new SaveFileDialog();
            expDialog.InitialDirectory = Utilities.Path.documentPath;
            expDialog.Filter = m_LocalView.SupportedFormats();
            
            if (System.IO.Path.HasExtension(fileName))
                fileName = System.IO.Path.GetFileNameWithoutExtension(fileName);
            expDialog.FileName = fileName;
            
            if (expDialog.ShowDialog() == DialogResult.OK)
            {
                DownloadInfo info = new DownloadInfo(d, type);
                downloadFromCloudThreadJob(info);
                //m_LocalView.DoDownloadDocument(info);

                if (info.m_Stream != null)
                {
                    try
                    {
                        CommonOperations.DoSaveContent(expDialog.OpenFile(), info.m_Stream);
                       
                        DocumentInfo chk_info = new DocumentInfo(null, null);
                        chk_info.m_DocEntry = d.DocumentEntry;
                        chk_info.m_FullName = expDialog.FileName;
                 
                        //convert document to the saved type: xls or xlsx
                        m_LocalView.CastContentToExtension(expDialog.FileName, type);
                        
                        m_dbOperations.DoRegisterLocalCopy(chk_info);

                        m_LocalView.DoOpenLocalCopy(expDialog.FileName);

                        m_LocalView.UpdateDocumentInfo();
                    }
                    catch (IOException ex)
                    {
                        Utilities.TraceWrapper.LogException("processNewDocument error: " + ex.Message, ex);
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

        private void processExistedDocument(Document d, Document.DownloadType type, string fileName)
        {
            SaveFileDialog expDialog = new SaveFileDialog();
            expDialog.InitialDirectory = Utilities.Path.documentPath;
            expDialog.FileName = fileName;

            Collision m_CollisionDialog = new Collision();
            DialogResult m_Result = m_CollisionDialog.ShowDialog();

            if (m_Result == DialogResult.OK)
            {
                bool is_collision_book_opened = m_LocalView.IsDocumentOpened(fileName);
                try
                {
                    if (m_CollisionDialog.m_ServerToLocal.Checked)
                    {
                        DownloadInfo info = new DownloadInfo(d, type);
                        downloadFromCloudThreadJob(info);
                        //m_LocalView.DoDownloadDocument(info);

                        // if collision's book is opened then close it
                        m_LocalView.CloseDocument(fileName);

                        CommonOperations.DoSaveContent(expDialog.OpenFile(), info.m_Stream);
                        
                        //convert document to the same type as extension
                        m_LocalView.CastContentToExtension(expDialog.FileName, type);
                        m_LocalView.DoOpenLocalCopy(expDialog.FileName);
                    }
                    else if (m_CollisionDialog.m_Merge.Checked)
                    {
                        if (is_collision_book_opened)
                            m_LocalView.ActivateDocument(fileName);
                        else
                            m_LocalView.DoOpenLocalCopy(expDialog.FileName);

                        m_LocalView.Merge(d, ILocalView.CollisionWinner.server);
                    }

                    m_LocalView.UpdateDocumentInfo();
                }
                catch (IOException ex)
                {
                    Utilities.TraceWrapper.LogException("processExistedDocument error: " + ex.Message, ex);
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void downloadDocument(object e)
        {
            try
            {
                //do not catch exception here
                DownloadInfo info = e as DownloadInfo;
                m_LocalView.DoDownloadDocument(info);
            }
            finally
            {
                m_TS_UI.SetEnabled(UpdateBtn, true);
                if (m_progressDlg.InvokeRequired)
                {
                    VoidDelegate dlg = new VoidDelegate(CloseProgreeDlg);
                    m_progressDlg.Invoke(dlg);
                }
                else m_progressDlg.Close();
            }
        }

        private void downloadFromCloudThreadJob(DownloadInfo info)
        {
            Thread newThread = new Thread(downloadDocument);
            newThread.SetApartmentState(ApartmentState.STA);
            newThread.Start(info);
            
            //if download happens earlier then we display progress, then ignore it at all
            if (m_progressDlg.IsDisposed == false)
                m_progressDlg.ShowDialog(this);
        }

        private void downloadFromCloud(object sender, TreeNodeMouseClickEventArgs e)
        {
            try
            {
                Document d = e.Node.Tag as Document;
                if ((d == null) || (d.Type != m_LocalView.DocumentType())) 
                    return;

                DocumentInfo chk_info = new DocumentInfo(null, null);
                chk_info.m_DocEntry = d.DocumentEntry;
                m_dbOperations.DoLookupLocalCopy(chk_info);

                Document.DownloadType type = m_LocalView.DownloadType();//Document.DownloadType.xls;

                if (chk_info.m_FullName == null)
                    processNewDocument(d, type, d.Title);
                else
                    processExistedDocument(d, type, chk_info.m_FullName);

                //UpdateBtn.Enabled = true;
           }
           catch (Exception ex)
           {
                Utilities.TraceWrapper.LogException("downloadFromCloud error: " + ex.Message, ex);

                m_TS_UI.SetText(StatusMessage, Properties.Resources.ErrorPrefix + ex.Message);
                //m_TS_UI.SetEnabled(RefreshButton, false);
           }
           finally
           {
                m_TS_UI.SetEnabled(UpdateBtn, true);
           }
        }

        private void Explorer_Resize(object sender, EventArgs e)
        {
            documentsView.Width = Explorer.Width - 30;
            documentsView.Height = Explorer.Height - 30;
        }

        private void documentsView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                if (documentsView.SelectedNode == null) return;
                Document d = e.Node.Tag as Document;
                if (d == null) return;
                if (d.Type == Document.DocumentType.Folder) return;

                ContextMenu treeContextMenu = new ContextMenu();
                treeContextMenu.MenuItems.Add("Open in Cloud", OnOpenInCloud);
                System.Drawing.Point pt = new System.Drawing.Point(documentsView.SelectedNode.Bounds.Left,
                                     documentsView.SelectedNode.Bounds.Bottom);
                try
                {
                    treeContextMenu.Show(documentsView, pt);
                }
                catch (Exception ex)
                {
                    Utilities.TraceWrapper.LogException("documentsView_NodeMouseClick error: " + ex.Message, ex);
                }
            }
        }

        private void OnOpenInCloud(Object sender, EventArgs e)
        {
            if (documentsView.SelectedNode == null) return;
            Document d = documentsView.SelectedNode.Tag as Document;
            if (d == null) return;
            DocumentInfo info = new DocumentInfo(null, null);
            info.m_DocEntry = d.DocumentEntry;

            m_LocalView.DoOpenDocumentInCloud(info);
        }

        private void documentsView_MouseDown(object sender, MouseEventArgs e)
        {
            SetSelectedNodeByPosition(documentsView, e.X, e.Y);

            if (documentsView.SelectedNode == null) { return; }

            if (e.Button == MouseButtons.Right) { return; }
        }

        private static void SetSelectedNodeByPosition(TreeView tv, int mouseX, int mouseY)
        {
            TreeNode node = null;

            try
            {
                System.Drawing.Point pt = new System.Drawing.Point(mouseX, mouseY);

                tv.PointToClient(pt);

                node = tv.GetNodeAt(pt);

                tv.SelectedNode = node;

                if (node == null) return;

                if (!node.Bounds.Contains(pt)) { return; }

            }
            catch(Exception ex) 
            {
                Utilities.TraceWrapper.LogException("SetSelectedNodeByPosition error: " + ex.Message, ex);
            }
        }

        public long LookAtContactsCount()
        {
            long l = ContactListBox.Items.Count;
            return l;
        }

        private void RefreshButton_Click(object sender, EventArgs e)
        {
            m_TS_UI.SetVisible(StatusMsgExplorer, false);
            
            try
            {
                BuildStructureDelegate dlgt1 = new BuildStructureDelegate(this.BuildDocuments);
                IAsyncResult ar = dlgt1.BeginInvoke(new AsyncCallback(BuildDataStructureCallbackMethod), dlgt1);
               
                //BuildDocuments(); 
            }
            catch (Exception ex)
            {
                Utilities.TraceWrapper.LogException("RefreshButton_Click error: " + ex.Message, ex);

                m_TS_UI.SetForeColor(StatusMsgExplorer, Color.Red);
                m_TS_UI.SetText(StatusMsgExplorer, Properties.Resources.ErrorPrefix + ex.Message);
                m_TS_UI.SetVisible(StatusMsgExplorer, true);
            }
        }

        private void RegistrationLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Registration regForm = new Registration(m_dbOperations);
            if (regForm.ShowDialog() == DialogResult.OK)
            {
                UserName.Enabled = true;
                Password.Enabled = true;
                checkRemember.Enabled = true;
                LoginButton.Enabled = true;
                RegistrationLink.Visible = false;
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                Process.Start(Properties.Resources.AppUrl);
            }
            catch (Win32Exception ex)
            {
                Utilities.TraceWrapper.LogException("linkLabel1_LinkClicked error: " + ex.Message, ex);

                //nothing is registered to handle URLs, so let's use IE!
                Process.Start("IExplore.exe", Properties.Resources.AppUrl);
            } 
 
        }

        private bool isCollisionExist(DocumentEntry doc1, DocumentEntry doc2)
        {
            if (doc1.Etag != doc2.Etag)
                return true;
            else
                return false;
        }

        private void DoAllUpdatesOppsInThread()
        {
            m_TS_UI.SetEnabled(UpdateBtn, false);
            m_TS_UI.SetVisible(StatusMsgUpdate, false);

            try
            {
                //get_current_document_path
                //get_current_document_name
                DocumentInfo info = new DocumentInfo(m_LocalView.GetDocumentPath(),
                                                     m_LocalView.GetDocumentName());
                m_LocalView.DoLookupRemoteCopy(info);
                if (info.m_DocEntry != null)
                {
                    //you open the already synced document from disk, you are able to update it, but it's null after opening
                    if (m_LocalView.m_DocInfo == null)
                        m_LocalView.m_DocInfo = info;

                    if (isCollisionExist(m_LocalView.m_DocInfo.m_DocEntry, info.m_DocEntry))
                    {
                        Collision m_CollisionDialog = new Collision();
                        DialogResult m_Result = m_CollisionDialog.ShowDialog();
                        if (m_Result == DialogResult.OK)
                        {
                            if (m_CollisionDialog.m_ServerToLocal.Checked)
                                //overwrite server content by local during applying the latest eTag
                                m_LocalView.m_DocInfo = info;
                            else
                            {
                                Document dt = new Document();
                                dt.AtomEntry = m_LocalView.m_DocInfo.m_DocEntry;
                                //merge the current content with server copy and put the result to the server
                                m_LocalView.Merge(dt, ILocalView.CollisionWinner.local);
                                m_LocalView.m_DocInfo = info;
                            }
                        }
                        else
                            return;
                    }

                    // the collision exist but user prefer to overwrite the server content
                    // the collision exist but it was already merged so we can put it to the server
                    //no collision exist, the local content is the latest content so we can put it to the server directly
                    try
                    {
                        m_LocalView.DoUpdateDocument();
                        
                        ShareInfoCollection infoShare = new ShareInfoCollection(m_LocalView.m_DocInfo.m_DocEntry);
                        m_LocalView.DoGetDocumentAcl(infoShare);

                        if (infoShare.m_Feed.Entries.Count() != 0 && checkBoxUpdateNotification.Checked)
                            this.SendNotification(infoShare.m_Feed,
                                                  this.UpdSubject.Text,
                                                  this.UpdMsg.Text,
                                                  this.m_LocalView.GetInviteUri(),
                                                  m_LocalView.m_DocInfo.m_Name,
                                                  MailNotificationTypes.Update);
                        //refresh eTag
                        m_LocalView.DoLookupRemoteCopy(m_LocalView.m_DocInfo);
                    }
                    catch (GDataRequestException ex)
                    {
                        //potentially could be very rare case that smb was able 
                        //to update document at the server during our collision resolution operation
                        Utilities.TraceWrapper.LogException("DoUpdateDocument error: " + ex.Message, ex);
                        HttpWebResponse ht = ex.Response as HttpWebResponse;
                        // if precondition error happens it means that somebody update document and we have to try update it again
                        if ((ht != null) && (ht.StatusCode == HttpStatusCode.PreconditionFailed))
                            DoAllUpdatesOppsInThread();
                        else
                            throw ex;
                    }
                }
                // if no document at the server we can do upload 
            }
            catch (GDataRequestException ex)
            {
                Utilities.TraceWrapper.LogException("UpdateBtn_Click error: " + ex.Message, ex);

                m_TS_UI.SetForeColor(StatusMsgUpdate, Color.Red);
                m_TS_UI.SetText(StatusMsgUpdate, Properties.Resources.ErrorPrefix + ex.Message);
                m_TS_UI.SetVisible(StatusMsgUpdate, true);
            }
            catch (Exception ex)
            {
                Utilities.TraceWrapper.LogException("UpdateBtn_Click error: " + ex.Message, ex);

                m_TS_UI.SetForeColor(StatusMsgUpdate, Color.Red);
                m_TS_UI.SetText(StatusMsgUpdate, Properties.Resources.ErrorPrefix + ex.Message);
                m_TS_UI.SetVisible(StatusMsgUpdate, true);
            }
            finally
            {
                m_TS_UI.SetEnabled(UpdateBtn, true);
                if (m_progressDlg.InvokeRequired)
                {
                    VoidDelegate dlg = new VoidDelegate(CloseProgreeDlg);
                    m_progressDlg.Invoke(dlg);
                }
                else m_progressDlg.Close();
 
            }
        }

        private void UpdateBtn_Click(object sender, EventArgs e)
        {
            if (m_multithreadSupported)
            {
                ThreadStart newThreadStart = new ThreadStart(DoAllUpdatesOppsInThread);
                Thread newThread = new Thread(newThreadStart);
                newThread.Start();

                m_progressDlg.ShowDialog(this);
            }
            else
                DoAllUpdatesOppsInThread();
        }

        private void MyGDocsTabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            //reset all errors messages
            m_TS_UI.SetVisible(StatusMessage, false);
            m_TS_UI.SetVisible(StatusMsgShare, false);
            m_TS_UI.SetVisible(StatusMsgUpdate, false);
            m_TS_UI.SetVisible(StatusMsgExplorer, false);
        }

        private void LoginButton_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                e.Handled = true;
                this.Login_Click(sender, null); 
            }
        }

 
        private void SendBtn_Click(object sender, EventArgs e)
        {
          try
            {
                MailMessage mail = new MailMessage();

                mail.To = "support@upriseapps.com";

                if (!this.m_LocalView.m_Cred.m_Cred.Username.Contains("@"))
                    mail.From = this.m_LocalView.m_Cred.m_Cred.Username + "@gmail.com";
                else
                    mail.From = this.m_LocalView.m_Cred.m_Cred.Username;

                if (SupportSubj.Text.Trim().Length == 0)
                    mail.Subject = Properties.Resources.FeedbackSubject;
                else
                    mail.Subject = SupportSubj.Text;

                mail.Body = Properties.Resources.MsgFeedbackPrefix;

                if (SupportMsg.Text.Trim().Length != 0)
                {
                    mail.Body += "\n";
                    mail.Body += SupportMsg.Text;
                }

                mail.Body += "\n";
                mail.Body += "With best wishes From Uprise Apps Office In Cloud.";

                m_traceWrapper.shutdownTraceListener();
                mail.Attachments.Add(new MailAttachment(Utilities.Path.logPath));

                PrepareSendMessage(mail);
            }
            catch (System.Exception ex)
            {
                m_traceWrapper.initTraceListener();
                Utilities.TraceWrapper.LogException("SendBtn_Click error: " + ex.Message, ex);
            }
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            ContentProcessor.ProcessText pr = new ContentProcessor.ProcessText();
            //KeywordsBox.Text = pr.DoAction(m_LocalView);

            //m_LocalView.SmartTagActions();
        }

        private void m_progressDlg_Load(object sender, EventArgs e)
        {

        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            if (txtSearch.Text.Trim() == "") return;
            listSearchResults.Items.Clear();
            
            try
            {
                List<ResultItem> m_List = new List<ResultItem>(); 
                m_TS_UI.SetEnabled(btnSearch, false);
                m_webContent.Search(txtSearch.Text.Trim(), m_List);

                foreach(ResultItem item in m_List)
                {
                    ListViewItem value = new ListViewItem();
                    value.ImageIndex = 2;
                    value.Text = item.Title;
                    value.ToolTipText = item.Description;
                    value.Tag = item.DisplayURL; 
                    m_TS_UI.AddSimpleListBoxItem(listSearchResults, value);
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                m_TS_UI.SetEnabled(btnSearch, true);
            }
        }

        private void lstSearchResults_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void listSearchResults_DragDrop(object sender, DragEventArgs e)
        {
            
        }

        private void listSearchResults_DoubleClick(object sender, EventArgs e)
        {
            if (listSearchResults.SelectedItems.Count == 0) return;

            foreach (ListViewItem item in listSearchResults.SelectedItems)
            {
                string[] result = new string[3];
                result[0] = item.Text;
                result[1] = item.ToolTipText;
                result[2] = "http://" + (string)item.Tag;
                m_LocalView.InsertSearchResult(result); 
            }
        }

        private void listSearchResults_MouseDown(object sender, MouseEventArgs e)
        {
            
        }

        private void ShareTab_Resize(object sender, EventArgs e)
        {
            this.ContactListBox.Width = this.ShareTab.Width - 30;
            this.ShareSubject.Width = this.ShareTab.Width - 30;
            this.ShareMsg.Width = this.ShareTab.Width - 30;

            this.txtTitle.Width = (int)(ShareTab.Width / 3) - 10;
            this.txtNewMail.Width = (int)(ShareTab.Width / 3) - 10;
            this.txtNewMail.Left = this.txtTitle.Left + txtTitle.Width + 2;
            this.label23.Left = txtNewMail.Left;
            this.btnAddMail.Left = this.txtNewMail.Left + this.txtNewMail.Width + 2;
        }

        private void UpdateTab_Resize(object sender, EventArgs e)
        {
            this.UpdSubject.Width = this.UpdateTab.Width - 30;
            this.UpdMsg.Width = this.UpdateTab.Width - 30;
        }

        private void tabWeb_Resize(object sender, EventArgs e)
        {
            this.txtSearch.Width = this.tabWeb.Width - this.btnSearch.Width - 30;
            this.btnSearch.Left = this.tabWeb.Width - this.btnSearch.Width - 10;
            this.listSearchResults.Width = this.tabWeb.Width - 20;
        }

        private void SupportTab_Resize(object sender, EventArgs e)
        {
            this.SupportSubj.Width = this.SupportTab.Width - 30;
            this.SupportMsg.Width = this.SupportTab.Width - 30;
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void maskedTextBox1_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
        {

        }

        private void btnApply_Click(object sender, EventArgs e)
        {
            // Save proxy settings to registry. 
            RegistryKey kHKCU = Registry.CurrentUser;
            RegistryKey kFirstRun;
            
            kFirstRun = kHKCU.OpenSubKey("Software\\UpriseApps\\OfficeInCloud", true);
            if (kFirstRun == null)
            {
                kFirstRun = kHKCU.CreateSubKey("Software\\UpriseApps\\OfficeInCloud", RegistryKeyPermissionCheck.ReadWriteSubTree);
                kFirstRun.SetValue("ProxyType", 0);
                // 0 - No Proxy
                // 1 - IE Proxy
                // 2 - Manual Proxy
            }
            if (radioNoProxy.Checked)
                kFirstRun.SetValue("ProxyType", 0);
            else if (radioIEProxy.Checked)
                kFirstRun.SetValue("ProxyType", 1);
            else if (radioManualProxy.Checked)
            {
                string address = maskedTextBox1.Text;
                string port = maskedTextBox2.Text;

                if (address.Length == 0)
                {
                    MessageBox.Show("Please specify the proxy address", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                if (port.Length == 0)
                {
                    MessageBox.Show("Please specify the proxy port", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                
                //if (port.Trim().Length > 0) address = address + ":" + port; 
                kFirstRun.SetValue("ProxyType", 2);
                kFirstRun.SetValue("ProxyAddress", address);
                kFirstRun.SetValue("ProxyPort", port); 
                kFirstRun.SetValue("UserName", textBox3.Text);
                kFirstRun.SetValue("Password", textBox4.Text);
            }
             
        }

        private void btnAddMail_Click(object sender, EventArgs e)
        {
            if (txtNewMail.Text.Trim().Length > 0)
            {
                try
                {
                    ContactInfo ci = new ContactInfo(txtTitle.Text, txtNewMail.Text);
                    m_LocalView.DoAddContact(ci);
                    if(ci.m_Contact!=null) AddContact2UI(ci.m_Contact);
                    txtTitle.Text = "";
                    txtNewMail.Text = ""; 
                }
                catch (Exception ex)
                {
                    Utilities.TraceWrapper.LogException("DoAddContact error: " + ex.Message, ex);
                    m_TS_UI.SetForeColor(StatusMsgExplorer, Color.Red);
                    m_TS_UI.SetText(StatusMsgExplorer, Properties.Resources.ErrorPrefix + ex.Message);
                    m_TS_UI.SetVisible(StatusMsgExplorer, true);
                }
            }
        }


    }
}
